package com.learning.springmvc.advance.valid.controller;

import com.learning.springmvc.advance.valid.bean.Address;
import com.learning.springmvc.advance.valid.bean.User;
import com.learning.springmvc.advance.valid.group.Group;
import com.learning.springmvc.advance.valid.group.Insert;
import com.learning.springmvc.advance.valid.group.Select;
import com.learning.springmvc.advance.valid.validator.UserLoginValidator;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * ClassName: UserController
 * Description:
 * Date: 2019/5/21 16:23 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@RestController
@RequestMapping("user")
public class UserController {

    /**
     * 注解 @Valid
     * ModelAttributeMethodProcessor 参数解析器
     * 没有处理结果返回，访问 400
     *
     * @param user
     * @return
     */
    @GetMapping("valid")
    public User valid(@Valid User user) {
        return user;
    }

    /**
     * 注解 @Validated
     * ModelAttributeMethodProcessor 参数解析器
     * 没有处理结果返回，访问 400
     *
     * @param user
     * @return
     */
    @GetMapping("validated")
    public User validated(@Validated User user) {

        return user;
    }

    /**
     * 使用方法参数处理结果返回：BindingResult或者Errors 作为参数
     * http://localhost:8080/user/get
     * http://localhost:8080/user/get?name=sam
     * <p>
     * ModelAttributeMethodProcessor 参数解析器
     * <p>
     * 结果：访问正常
     *
     * @param user
     * @return
     */
    @GetMapping("get")
    public User get(@Validated User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            // 错误数据返回打印
            System.out.println(bindingResult.getFieldError());
            return null;
        }
        return user;
    }


    /**
     * 可以使用统一异常处理
     * <p>
     * http://localhost:8080/user/get2
     * http://localhost:8080/user/get2?name=sam
     *
     * @param user
     * @return
     */
    @GetMapping("get2")
    public User get(@Validated User user) {
        return user;
    }


    /**
     * 分组。
     * <p>
     * - @UserConstraint name 必须是eason
     * - name 属性不能为空
     * - mobile 在 Insert 分组时不能为空
     * - birthday 在 Select 分组时不能为空
     *
     * @param user
     * @return
     */
    @GetMapping("groupSelect")
    public User group(@Validated(Select.class) User user) {
        return user;
    }

    /**
     * 分组
     *
     * @param user
     * @return
     */
    @GetMapping("groupInsert")
    public User group2(@Validated(Insert.class) User user) {
        return user;
    }

    /**
     * 组序列
     *
     * @param user
     * @return
     */
    @GetMapping("groupSequence")
    public User groupSequence(@Validated(Group.class) User user) {
        return user;
    }


    /**
     * 自定义校验器
     * http://localhost:8080/user/loginValidator
     *
     * @param user
     * @return
     */
    @GetMapping("loginValidator")
    public User loginValidator(User user, BindingResult result) {
        // 直接使用校验
        ValidationUtils.rejectIfEmptyOrWhitespace(result, "name", "name不能为空");
        ValidationUtils.rejectIfEmptyOrWhitespace(result, "mobile", "mobile不能为空");

        if (result.hasErrors()) {
            System.out.println(result.getFieldError());
            return null;
        }

        return user;
    }

    /**
     * 自定义校验
     * http://localhost:8080/user/cusValidator?name=sam&mobile=123
     *
     * @param user
     * @return
     */
    @GetMapping("cusValidator")
    public User cusValidator(@Validated User user) {
        return user;
    }

    /**
     * 绑定。该类所有的接口，都使用该校验器，覆盖springmvc 框架的实现
     * 如果有其他类型标注了校验，会报错，慎用。
     *
     * @param binder
     */
    @InitBinder
    public void binder(WebDataBinder binder) {
        binder.setValidator(new UserLoginValidator());
    }

}